#ifndef _WX_DATAOBJ_H_BASE_
#define _WX_DATAOBJ_H_BASE_

#include "wx/defs.h"

#if wxUSE_DATAOBJ

#include "wx/string.h"
#include "wx/bitmap.h"
#include "wx/list.h"
#include "wx/arrstr.h"


#include "wx/gtk/dataform.h"

extern const wxDataFormat& wxFormatInvalid;

class wxDataObjectBase {
  public:
    enum Direction {
      Get  = 0x01,    // format is supported by GetDataHere()
      Set  = 0x02,    // format is supported by SetData()
      Both = 0x03     // format is supported by both (unused currently)
    };
    virtual ~wxDataObjectBase();
    virtual wxDataFormat GetPreferredFormat( Direction dir = Get ) const = 0;
    virtual size_t GetFormatCount( Direction dir = Get ) const = 0;
    virtual void GetAllFormats( wxDataFormat *formats,
                                Direction dir = Get ) const = 0;
    virtual size_t GetDataSize( const wxDataFormat& format ) const = 0;
    virtual bool GetDataHere( const wxDataFormat& format, void *buf ) const = 0;
    virtual bool SetData( const wxDataFormat& ( format ),
                          size_t ( len ), const void * ( buf ) ) {
      return false;
    }
    bool IsSupported( const wxDataFormat& format, Direction dir = Get ) const;
};

#include "wx/gtk/dataobj.h"

class wxDataObjectSimple : public wxDataObject {
  public:
    wxDataObjectSimple( const wxDataFormat& format = wxFormatInvalid )
      : m_format( format ) {
    }
    const wxDataFormat& GetFormat() const { return m_format; }
    void SetFormat( const wxDataFormat& format ) { m_format = format; }
    virtual size_t GetDataSize() const
    { return 0; }
    virtual bool GetDataHere( void *( buf ) ) const
    { return false; }
    virtual bool SetData( size_t ( len ), const void *( buf ) ) { return false; }
    virtual wxDataFormat GetPreferredFormat( wxDataObjectBase::Direction dir = Get ) const
    { return m_format; }
    virtual size_t GetFormatCount( wxDataObjectBase::Direction ( dir ) = Get ) const
    { return 1; }
    virtual void GetAllFormats( wxDataFormat *formats, wxDataObjectBase::Direction ( dir ) = Get ) const {
      *formats = m_format;
    }
    virtual size_t GetDataSize( const wxDataFormat& ( format ) ) const {
      return GetDataSize();
    }
    virtual bool GetDataHere( const wxDataFormat& ( format ), void *buf ) const {
      return GetDataHere( buf );
    }
    virtual bool SetData( const wxDataFormat&  format, size_t len, const void *buf ) {
      return SetData( len, buf );
    }

  private:
    wxDataFormat m_format;

    DECLARE_NO_COPY_CLASS( wxDataObjectSimple )
};

WX_DECLARE_EXPORTED_LIST( wxDataObjectSimple, wxSimpleDataObjectList );

class wxDataObjectComposite : public wxDataObject {
  public:
    wxDataObjectComposite();
    virtual ~wxDataObjectComposite();
    void Add( wxDataObjectSimple *dataObject, bool preferred = false );
    wxDataFormat GetReceivedFormat() const;
    virtual wxDataFormat GetPreferredFormat( wxDataObjectBase::Direction dir = Get ) const;
    virtual size_t GetFormatCount( wxDataObjectBase::Direction dir = Get ) const;
    virtual void GetAllFormats( wxDataFormat *formats, wxDataObjectBase::Direction dir = Get ) const;
    virtual size_t GetDataSize( const wxDataFormat& format ) const;
    virtual bool GetDataHere( const wxDataFormat& format, void *buf ) const;
    virtual bool SetData( const wxDataFormat& format, size_t len, const void *buf );

  protected:
    wxDataObjectSimple *GetObject( const wxDataFormat& format ) const;
  private:
    wxSimpleDataObjectList m_dataObjects;
    size_t m_preferred;
    wxDataFormat m_receivedFormat;
    DECLARE_NO_COPY_CLASS( wxDataObjectComposite )
};

class wxTextDataObject : public wxDataObjectSimple {
  public:
    // ctor: you can specify the text here or in SetText(), or override
    // GetText()
    wxTextDataObject( const wxString& text = wxEmptyString )
      : wxDataObjectSimple(
          wxDF_UNICODETEXT
        ),
        m_text( text ) {
    }

    virtual size_t GetTextLength() const { return m_text.Len() + 1; }
    virtual wxString GetText() const { return m_text; }
    virtual void SetText( const wxString& text ) { m_text = text; }

    #if wxUSE_UNICODE && (defined(__WXGTK20__) || defined(__WXMAC__))
    virtual size_t GetFormatCount( Direction dir = Get ) const { return 2; }
    virtual void GetAllFormats( wxDataFormat *formats, wxDataObjectBase::Direction dir = Get ) const;

    virtual size_t GetDataSize() const { return GetDataSize( GetPreferredFormat() ); }
    virtual bool GetDataHere( void *buf ) const { return GetDataHere( GetPreferredFormat(), buf ); }
    virtual bool SetData( size_t len, const void *buf ) { return SetData( GetPreferredFormat(), len, buf ); }

    size_t GetDataSize( const wxDataFormat& format ) const;
    bool GetDataHere( const wxDataFormat& format, void *pBuf ) const;
    bool SetData( const wxDataFormat& format, size_t nLen, const void* pBuf );
    #else
    virtual size_t GetDataSize() const;
    virtual bool GetDataHere( void *buf ) const;
    virtual bool SetData( size_t len, const void *buf );
    // Must provide overloads to avoid hiding them (and warnings about it)
    virtual size_t GetDataSize( const wxDataFormat& ) const {
      return GetDataSize();
    }
    virtual bool GetDataHere( const wxDataFormat&, void *buf ) const {
      return GetDataHere( buf );
    }
    virtual bool SetData( const wxDataFormat&, size_t len, const void *buf ) {
      return SetData( len, buf );
    }
    #endif

  private:
    wxString m_text;

    DECLARE_NO_COPY_CLASS( wxTextDataObject )
};

// ----------------------------------------------------------------------------
// wxBitmapDataObject contains a bitmap
// ----------------------------------------------------------------------------

class wxBitmapDataObjectBase : public wxDataObjectSimple {
  public:
    // ctor: you can specify the bitmap here or in SetBitmap(), or override
    // GetBitmap()
    wxBitmapDataObjectBase( const wxBitmap& bitmap = wxNullBitmap )
      : wxDataObjectSimple( wxDF_BITMAP ), m_bitmap( bitmap ) {
    }

    // virtual functions which you may override if you want to provide data on
    // demand only - otherwise, the trivial default versions will be used
    virtual wxBitmap GetBitmap() const { return m_bitmap; }
    virtual void SetBitmap( const wxBitmap& bitmap ) { m_bitmap = bitmap; }

  protected:
    wxBitmap m_bitmap;

    DECLARE_NO_COPY_CLASS( wxBitmapDataObjectBase )
};

// ----------------------------------------------------------------------------
// wxFileDataObject contains a list of filenames
//
// NB: notice that this is a "write only" object, it can only be filled with
//     data from drag and drop operation.
// ----------------------------------------------------------------------------

class wxFileDataObjectBase : public wxDataObjectSimple {
  public:
    // ctor: use AddFile() later to fill the array
    wxFileDataObjectBase() : wxDataObjectSimple( wxDF_FILENAME ) { }

    // get a reference to our array
    const wxArrayString& GetFilenames() const { return m_filenames; }

  protected:
    wxArrayString m_filenames;

    DECLARE_NO_COPY_CLASS( wxFileDataObjectBase )
};

// ----------------------------------------------------------------------------
// wxCustomDataObject contains arbitrary untyped user data.
//
// It is understood that this data can be copied bitwise.
// ----------------------------------------------------------------------------

class wxCustomDataObject : public wxDataObjectSimple {
  public:
    // if you don't specify the format in the ctor, you can still use
    // SetFormat() later
    wxCustomDataObject( const wxDataFormat& format = wxFormatInvalid );

    // the dtor calls Free()
    virtual ~wxCustomDataObject();

    // you can call SetData() to set m_data: it will make a copy of the data
    // you pass - or you can use TakeData() which won't copy anything, but
    // will take ownership of data (i.e. will call Free() on it later)
    void TakeData( size_t size, void *data );

    // this function is called to allocate "size" bytes of memory from
    // SetData(). The default version uses operator new[].
    virtual void *Alloc( size_t size );

    // this function is called when the data is freed, you may override it to
    // anything you want (or may be nothing at all). The default version calls
    // operator delete[] on m_data
    virtual void Free();

    // get data: you may override these functions if you wish to provide data
    // only when it's requested
    virtual size_t GetSize() const { return m_size; }
    virtual void *GetData() const { return m_data; }

    // implement base class pure virtuals
    // ----------------------------------
    virtual size_t GetDataSize() const;
    virtual bool GetDataHere( void *buf ) const;
    virtual bool SetData( size_t size, const void *buf );
    // Must provide overloads to avoid hiding them (and warnings about it)
    virtual size_t GetDataSize( const wxDataFormat& ) const {
      return GetDataSize();
    }
    virtual bool GetDataHere( const wxDataFormat&, void *buf ) const {
      return GetDataHere( buf );
    }
    virtual bool SetData( const wxDataFormat&, size_t len, const void *buf ) {
      return SetData( len, buf );
    }

  private:
    size_t m_size;
    void  *m_data;

    DECLARE_NO_COPY_CLASS( wxCustomDataObject )
};

// ----------------------------------------------------------------------------
// include platform-specific declarations of wxXXXBase classes
// ----------------------------------------------------------------------------

#include "wx/gtk/dataobj2.h"

// wxURLDataObject is simply wxTextDataObject with a different name
class wxURLDataObject : public wxTextDataObject {
  public:
    wxURLDataObject( const wxString& url = wxEmptyString )
      : wxTextDataObject( url ) {
    }

    wxString GetURL() const { return GetText(); }
    void SetURL( const wxString& url ) { SetText( url ); }
};

#endif // wxUSE_DATAOBJ

#endif // _WX_DATAOBJ_H_BASE_
